package com.demo.modules.sys.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.demo.common.base.QueryBase;
import com.demo.common.constant.Constant;
import com.demo.common.exception.RRException;
import com.demo.common.utils.PageUtils;
import com.demo.config.cache.ObjectCacheConfig;
import com.demo.modules.sys.dao.SysUserDao;
import com.demo.modules.sys.entity.SysMenuEntity;
import com.demo.modules.sys.entity.SysUserEntity;
import com.demo.modules.sys.form.SysUserQueryForm;
import com.demo.modules.sys.service.SysUserRoleService;
import com.demo.modules.sys.service.SysUserService;
import lombok.AllArgsConstructor;
import org.apache.commons.lang.RandomStringUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.shiro.crypto.hash.Sha256Hash;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Arrays;
import java.util.List;


/**
 * 系统用户
 *
 * @author Mark sunlightcs@gmail.com
 */
@Service("sysUserService")
@AllArgsConstructor
public class SysUserServiceImpl extends ServiceImpl<SysUserDao, SysUserEntity> implements SysUserService {

    private final SysUserRoleService sysUserRoleService;

    @Override
    public PageUtils<SysUserEntity> queryPage(SysUserQueryForm params) {
        IPage<SysUserEntity> page = this.page(
                new QueryBase<SysUserEntity>().getPage(params),
                new QueryBase<SysUserEntity>().getQuery(SysUserQueryForm.getQueryWrapper(params), params)
        );
        return new PageUtils<SysUserEntity>(page);
    }

    @Override
    public List<SysUserEntity> queryList(SysUserQueryForm params) {
        return this.list(new QueryBase<SysUserEntity>().getQuery(SysUserQueryForm.getQueryWrapper(params), params));
    }

    @Override
    public List<String> queryAllPerms(Long userId) {
        return baseMapper.queryAllPerms(userId);
    }

    @Override
    public List<Long> queryAllMenuId(Long userId) {
        return baseMapper.queryAllMenuId(userId);
    }

    @Override
    public List<SysMenuEntity> queryAllMenu(Long userId) {
        return baseMapper.queryAllMenu(userId);
    }

    @Override
    public SysUserEntity queryByUserName(String username) {
        return baseMapper.queryByUserName(username);
    }

    @Override
    public SysUserEntity queryByMobile(String mobile) {
        return baseMapper.selectOne(new QueryWrapper<SysUserEntity>().eq("mobile", mobile));
    }

    @Override
    public SysUserEntity queryByOpenId(String openid) {
        return baseMapper.selectOne(new QueryWrapper<SysUserEntity>().eq("openid", openid));
    }

    @Override
    public List<SysUserEntity> listAll() {
        return this.list(new LambdaQueryWrapper<SysUserEntity>()
                .eq(SysUserEntity::getIsDel, Constant.INT_N)
                .or()
                .eq(SysUserEntity::getIsDel, Constant.INT_Y)
        );
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void saveUser(SysUserEntity user) {
        this.saveValid(user);
        if (StrUtil.isNotBlank(user.getPassword())) {
            //sha256加密
            String salt = RandomStringUtils.randomAlphanumeric(20);
            user.setPassword(new Sha256Hash(user.getPassword(), salt).toHex());
            user.setSalt(salt);
        }
        this.save(user);

        //保存用户与角色关系
        sysUserRoleService.saveOrUpdate(user.getId(), user.getRoleIdList());

        //更新缓存
        ObjectCacheConfig.userCache.put(user.getId(), user);
    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    public void update(SysUserEntity user) {
        this.saveValid(user);
        if (StringUtils.isBlank(user.getPassword())) {
            user.setPassword(null);
        } else {
            user.setPassword(new Sha256Hash(user.getPassword(), user.getSalt()).toHex());
        }
        this.updateById(user);

        //保存用户与角色关系
        sysUserRoleService.saveOrUpdate(user.getId(), user.getRoleIdList());

        //更新缓存
        ObjectCacheConfig.userCache.put(user.getId(), user);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteBatch(Long[] ids) {
        List<Long> idList = Arrays.asList(ids);

        List<SysUserEntity> users = (List<SysUserEntity>) this.listByIds(idList);
        users.forEach(user -> {
            if (user.getIsAdmin() == Constant.INT_Y) {
                user.setIsAdmin(Constant.INT_N);
                super.updateById(user);
            } else {
                super.removeById(user.getId());
            }
        });
    }

    @Override
    public boolean updatePassword(Long userId, String password, String newPassword) {
        SysUserEntity userEntity = new SysUserEntity();
        userEntity.setPassword(newPassword);
        return this.update(userEntity,
                new QueryWrapper<SysUserEntity>().lambda()
                        .eq(SysUserEntity::getId, userId)
                        .eq(SysUserEntity::getPassword, password)
        );
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateBatch(SysUserEntity user, Long[] ids) {
        List<Long> idList = Arrays.asList(ids);

        idList.forEach(id -> {
            SysUserEntity nowUser = new SysUserEntity();
            BeanUtil.copyProperties(user, nowUser);
            nowUser.setId(id);
            this.saveValid(nowUser);
            if (StrUtil.isNotBlank(nowUser.getPassword())) {
                //sha256加密
                String salt = RandomStringUtils.randomAlphanumeric(20);
                nowUser.setPassword(new Sha256Hash(nowUser.getPassword(), salt).toHex());
                nowUser.setSalt(salt);
            }
            this.updateById(nowUser);
            nowUser = this.getById(id);
            //更新缓存
            ObjectCacheConfig.userCache.put(nowUser.getId(), nowUser);
        });
    }

    /**
     * 用户保存校验
     *
     * @param entity 用户对象
     */
    private void saveValid(SysUserEntity entity) {
        // 判断编码是否重复
        List<SysUserEntity> users = this.list(new QueryWrapper<SysUserEntity>().lambda()
                .eq(SysUserEntity::getUsername, entity.getUsername())
                .ne(entity.getId() != null, SysUserEntity::getId, entity.getId()));
        if (CollectionUtil.isNotEmpty(users)) {
            throw new RRException("用户名已存在，不能保存");
        }
    }
}
